Home:ALL Converter>C++ Factory Pattern implementation - example, questions, and concerns

C++ Factory Pattern implementation - example, questions, and concerns

Ask Time:2019-06-02T21:21:52         Author:cdahms

Json Formatter

I've been attempting to get a better understanding of using a Factory Pattern in C++ lately.

I've consulted the following resources:

How to implement the factory method pattern in C++ correctly

https://www.geeksforgeeks.org/design-patterns-set-2-factory-method/

https://sourcemaking.com/design_patterns/factory_method/cpp/1

https://www.codeproject.com/Articles/363338/Factory-Pattern-in-Cplusplus

https://www.bogotobogo.com/DesignPatterns/factorymethod.php

https://gist.github.com/pazdera/1099562

https://en.wikibooks.org/wiki/C%2B%2B_Programming/Code/Design_Patterns

Before somebody marks this as "Not a question", I do have some explicit questions which I'll get to in a moment. But to clarify my understanding so far first I'd like to start with an example. This is the best example I've been able to make from the information in the above links (best meaning illustrates the Factory Pattern but is as simple as possible so beginners to this pattern can plainly see the issues involved):

// FactoryPattern.cpp

#include <iostream>
#include <vector>

enum AnimalSpecies { dog, cat };


class Animal
{
public:
  virtual void makeSound() = 0;
};

class Dog : public Animal
{
public:
  void makeSound() { std::cout << "woof" << "\n\n"; }
};

class Cat : public Animal
{
public:
  void makeSound() { std::cout << "meow" << "\n\n"; }
};

class AnimalFactory
{
public:
  static Animal* makeAnimal(AnimalSpecies animalSpecies);
};

Animal* AnimalFactory::makeAnimal(AnimalSpecies animalSpecies)
{
  if (animalSpecies == AnimalSpecies::dog)
  {
    return(new Dog());
  }
  else if (animalSpecies == AnimalSpecies::cat)
  {
    return(new Cat());
  }
  else
  {
    std::cout << "error in AnimalFactory::makeAnimal(), animalSpecies = " << animalSpecies << " does not seem to be valid" << "\n\n";
    return(nullptr);
  }
}

int main(void)
{
  std::vector<Animal*> animals;

  animals.push_back(AnimalFactory::makeAnimal(AnimalSpecies::dog));
  animals.push_back(AnimalFactory::makeAnimal(AnimalSpecies::cat));

  for (auto &animal : animals)
  {
    animal->makeSound();
  }

  for (auto& animal : animals)
  {
    delete(animal);
  }

  return(0);
}

The output of this program (as intended) is:

woof

meow

Here are my questions at this time:

1) Some of the reading I've done on the Factory Pattern has led me to believe that eliminating if statements is part of the benefit. The above example fails in that regard since in AnimalFactory::makeAnimal() an if-else has to be used to determine species. Is there a way to refactor this to remove if statements?

2) With the various changes and improvements in C++ 14/17/20 lately, many of us are moving away from pointers to avoid the possibility of memory leaks. Is there a way to refactor this so as to not use pointers?

3) What is the advantage of the Factory Pattern? i.e. in the above example why not omit class AnimalFactory and simply make main() as follows:

int main(void)
{
  Dog dog;
  dog.makeSound();

  Cat cat;
  cat.makeSound();

  return(0);
}

Author:cdahms,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/56415444/c-factory-pattern-implementation-example-questions-and-concerns
IdeaHat :

\n has led me to believe that eliminating if statements is part of the benefit.\n\n\nIMHO the real power from the factory pattern comes from virtualizing the factory pattern:\n\nclass AnimalFactoryInterface\n{\n public:\n virtual Animal* makeAnimal() = 0;\n};\n\nclass CatFactory : public AnimalFactoryInterface\n{\n public:\n Animal* makeAnimal() override { return new Cat(); }\n};\n\n\nThis virtualizes how to create new animals, something impossible to do otherwise.\n\nThe switch statement constructor is useful for making animals from a config file, but that isn't really the power here. It helps when creating a generic Breeder class which accepts how to make generic animals.\n\n\n 2) With the various changes and improvements in C++ 14/17/20 lately, many of us are moving away from pointers to avoid the possibility of memory leaks. Is there a way to refactor this so as to not use pointers?\n\n\nReturn smart pointers (std::unique_ptr<Animal>).\n\n\n 3) What is the advantage of the Factory Pattern? i.e. in the above example why not omit class AnimalFactory and simply make main() as follows:\n\n\nFirst it makes it easy to do\n\nclass Breeder {\n public:\n Breeder(std::unique_ptr<AnimalFactoryInterface> animal_factory);\n void Breed() { animals_.push_back(animal_factory_->Create()); }\n // ... more stuff\n private:\n std::unique_ptr<AnimalFactoryInterface> animal_factory_;\n std::vector<std::unique_ptr<Animal>> animals_;\n};\n\n\nSecond is Dependency Injection.\n\nWe should also clarify \"the factory pattern\".\n\nThe thing I've described in this answer is the Abstract Factory Pattern - that is, utilizing a factory interface to create objects.\n\nUtilizing a single method with a switch statement to create objects is the Factory Method Pattern. It definitely has its utilities, but I've always found it a bit too obvious to anchor too much on as full \"design pattern\". But salient to this question, and to the advantages question, is that if all you're doing is simply making a series of objects, then you're right - you definitely don't need a factory class, and you don't even need a special method if all you're doing is making the classes once. A rule of thumb for any programming is do the simplest thing that works. ",
2019-06-02T14:05:48
yy